﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using BBICMS.Repository;
using BBICMS.Model;
using BBICMS.Model.Security;
using BBICMS.Model.ViewModel.Identity;
using System.Threading;
using SIG.Infrastructure.Helper;
using System.Web.Security;
using System.Web;
using Newtonsoft.Json;
using BBICMS.Infrastructure.Configs;
using BBICMS.Data.Extensions;

namespace BBICMS.Data.Repositories.Identity
{
    public class UserRepository : GenericRepository<User>, IUserRepository
    {
        public UserRepository(DbContext context) : base(context) { }


        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="model"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<User> SignIn(LoginVM model, CancellationToken cancellationToken = default(CancellationToken))
        {
            User user = await this.GetFirstOrDefaultAsync((u => u.UserName == model.UserName), cancellationToken, (u => u.Roles));


            if (user != null)
            {
                // byte[] salt = Encoding.UTF8.GetBytes(user.SecurityStamp);
                byte[] salt = Convert.FromBase64String(user.SecurityStamp);
                string pwdHash = Hash.HashPasswordWithSalt(model.Password, salt);

                if (user.PasswordHash == pwdHash)
                {
                  //  _logger.Info(string.Format(Logs.UserLoginMessage, user.UserName));
                    return user;
                }
                else
                    return null;
            }

            return null;
        }



        public int SearchUsersCount(string username, DateTime? startDate, DateTime? endDate)
        {
            var users = this.GetAll();
            users = users.SetFilters(username, startDate, endDate);

            return users.Count();
        }

        public IEnumerable<User> SearchUsers(int pageIndex, int pageSize, string username, DateTime? startDate, DateTime? endDate)
        {
            var users = this.GetAll();

            users = users.SetFilters(username, startDate, endDate);

            var result = users
                .OrderBy(l => l.UserName)
                .Skip(pageIndex * pageSize).Take(pageSize).AsEnumerable();

            return result;
        }


        /// <summary>
        /// 重设密码
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="password"></param>
        /// <returns></returns>

        public bool SetPassword(Guid userId, string password)

        {
            var user = this.GetById(userId);
            try
            {

                var securityStamp = Hash.GenerateSalt();
                var pwdHash = Hash.HashPasswordWithSalt(password, securityStamp);

                user.SecurityStamp = Convert.ToBase64String(securityStamp);
                user.PasswordHash = pwdHash;
                this.Update(user);                
                //log 
               // _logger.Info(string.Format(Logs.RestPwdMessage, user.EntityName, user.UserName));

                return true;
            }
            catch (Exception er)
            {
               // var message = String.Format(Logs.ErrorRestPwdMessage, user.EntityName);
               // _logger.Error(message, er);
                return false;
            }
            
        }

        public int ChangePassword(Guid userId, string oldPassword, string newPassword)
        {
            User user = GetById(userId);

            if (user != null)
            {
                // byte[] salt = Encoding.UTF8.GetBytes(user.SecurityStamp);
                byte[] salt = Convert.FromBase64String(user.SecurityStamp);
                string pwdHash = Hash.HashPasswordWithSalt(oldPassword, salt);

                if (user.PasswordHash == pwdHash)
                {
                    var securityStamp = Hash.GenerateSalt();
                    pwdHash = Hash.HashPasswordWithSalt(newPassword, securityStamp);

                    user.SecurityStamp = Convert.ToBase64String(securityStamp);
                    user.PasswordHash = pwdHash;
                    this.Update(user);

                    return 0;
                }
                else
                {
                    return 2; //2 原密码不正确
                }
                    
            }

            return 1; //1 用户不存在
        }

        public bool IsEmailUniqueAtEdit(string email, Guid id)
        {
            var result = this.GetAll().Any(u => u.Email == email && u.Id != id);
            if (result)
                return false;

            return true;
        }


        public Task<User> GetUserByName(string userName, CancellationToken cancellationToken = default(CancellationToken))
        {
            return this.GetFirstOrDefaultAsync((u => u.UserName == userName), cancellationToken, (u => u.Roles));
        }
        public Task<User> GetUserByEmail(string email, CancellationToken cancellationToken = default(CancellationToken))
        {
            return this.GetFirstOrDefaultAsync((u => u.Email == email), cancellationToken, (u => u.Roles));
        }


        public int Register(RegisterVM user)
        {
            var orgUsers = this.GetFilteredElements(u => u.Email == user.Email);
            if (orgUsers.Count() > 0)
            {
                return 1; //1 邮箱已存在
            }

            orgUsers = this.GetFilteredElements(u => u.UserName == user.UserName);
            if (orgUsers.Count() > 0)
            {
                return 2; //1 用户名已存在
            }

            var securityStamp = Hash.GenerateSalt();
                var passwordHash = Hash.HashPasswordWithSalt(user.Password, securityStamp);

                var newUser = new User()
                {
                    UserName = user.UserName,
                    RealName = user.DisplayName,
                    Email = user.Email,
                    SecurityStamp = Convert.ToBase64String(securityStamp),
                    PasswordHash = passwordHash,
                    CreateDate = DateTime.Now,
                    IsActive = true
                };

                //  _logger.Info(string.Format(Logs.CreateMessage, newUser.EntityName, user.UserName));
                this.Add(newUser);
                _context.SaveChanges();

                return 0;
            



        }

    }
}